﻿using Gonte.Xml;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System;
using Gonte;
using Gonte.Xml.Serialization;

namespace MyUtilitiesTest
{
    /// <summary>
    ///This is returnedAttributes test class for XmlObjectSerializerTest and is intended
    ///to contain all XmlObjectSerializerTest Unit Tests
    ///</summary>
    [TestClass()]
    public class XmlObjectSerializerTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in returnedAttributes class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        #region Primitives

        [TestMethod()]
        public void SerializePrimitiveString()
        {
            String obj = "Jorge";
            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<String>Jorge</String>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializePrimitiveGuid()
        {
            Guid obj = new Guid("5daa64c2-2c28-47d7-86d4-0dc378a0568b");
            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<Guid>5daa64c2-2c28-47d7-86d4-0dc378a0568b</Guid>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializePrimitiveDateTime()
        {
            DateTime obj = new DateTime(2005, 5, 25, 2, 30, 18);
            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<DateTime>5/25/2005 2:30:18 AM</DateTime>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializePrimitiveEnumeration()
        {
            EnumerationTest obj = EnumerationTest.EnumItem2;
            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<EnumerationTest>EnumItem2</EnumerationTest>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        } 

        #endregion

        #region Objects

        [TestMethod()]
        public void SerializeWithRootAttribute()
        {
            SimpleObjectWithRootAttribute obj = new SimpleObjectWithRootAttribute();
            obj.Name = "MyName";

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<MyObject Name=""MyName"" />";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializeObjectWithPrimitives()
        {
            ObjectWithPrimitivesTest obj = new ObjectWithPrimitivesTest();
            obj.GuidProp = new Guid("3b72d25f-0a74-47a3-ae3d-c223af92ec8b");
            obj.DatetimeProp = new DateTime(2002, 5, 25, 2, 30, 18);
            obj.DecimalProp = 125000.43M;
            obj.DoubleProp = 0.005;
            obj.IntProp = 65;
            obj.StringProp = "My string property";

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<ObjectWithPrimitivesTest StringProp=""My string property"" GuidProp=""3b72d25f-0a74-47a3-ae3d-c223af92ec8b"" DatetimeProp=""5/25/2002 2:30:18 AM"" DecimalProp=""125000.43"" DoubleProp=""0.005"" IntProp=""65"" />";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializeObjectWithInnerObject()
        {
            ObjectWithInnerObjectAndPrimitivesTest obj = new ObjectWithInnerObjectAndPrimitivesTest();
            obj.StringProp = "Another string property";
            obj.IntProp = 23432;

            ObjectWithPrimitivesTest innerObject = new ObjectWithPrimitivesTest();
            innerObject.GuidProp = new Guid("3b72d25f-0a74-47a3-ae3d-c223af92ec8b");
            innerObject.DatetimeProp = new DateTime(2002, 5, 25, 2, 30, 18);
            innerObject.DecimalProp = 125000.43M;
            innerObject.DoubleProp = 0.005;
            innerObject.IntProp = 65;
            innerObject.StringProp = "My string property";

            obj.InnerObject = innerObject;

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<ObjectWithInnerObjectAndPrimitivesTest StringProp=""Another string property"" IntProp=""23432"">
  <InnerObject StringProp=""My string property"" GuidProp=""3b72d25f-0a74-47a3-ae3d-c223af92ec8b"" DatetimeProp=""5/25/2002 2:30:18 AM"" DecimalProp=""125000.43"" DoubleProp=""0.005"" IntProp=""65"" />
</ObjectWithInnerObjectAndPrimitivesTest>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }
        
        #endregion

        [TestMethod()]
        public void SerializeListOfStrings()
        {
            List<String> obj = new List<String>();
            obj.Add("Toyota");
            obj.Add("Honda");
            obj.Add("Hyundai");
            obj.Add("Acura");

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<List>
  <String>Toyota</String>
  <String>Honda</String>
  <String>Hyundai</String>
  <String>Acura</String>
</List>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializeListOfComplexObjects()
        {
            List<ObjectWithInnerObjectAndPrimitivesTest> obj = new List<ObjectWithInnerObjectAndPrimitivesTest>();

            ObjectWithInnerObjectAndPrimitivesTest item1 = new ObjectWithInnerObjectAndPrimitivesTest();
            item1.StringProp = "Another string property";
            item1.IntProp = 23432;

            ObjectWithPrimitivesTest innerObject1 = new ObjectWithPrimitivesTest();
            innerObject1.GuidProp = new Guid("3b72d25f-0a74-47a3-ae3d-c223af92ec8b");
            innerObject1.DatetimeProp = new DateTime(2002, 5, 25, 2, 30, 18);
            innerObject1.DecimalProp = 125000.43M;
            innerObject1.DoubleProp = 0.005;
            innerObject1.IntProp = 65;
            innerObject1.StringProp = "My string property";

            item1.InnerObject = innerObject1;

            obj.Add(item1);

            ObjectWithInnerObjectAndPrimitivesTest item2 = new ObjectWithInnerObjectAndPrimitivesTest();
            item2.StringProp = "Another string property2";
            item2.IntProp = 23432;

            ObjectWithPrimitivesTest innerObject3 = new ObjectWithPrimitivesTest();
            innerObject3.GuidProp = new Guid("4b72d25f-0a74-47a3-ae3d-c223af92ec8b");
            innerObject3.DatetimeProp = new DateTime(2003, 6, 25, 2, 30, 18);
            innerObject3.DecimalProp = 225000.43M;
            innerObject3.DoubleProp = 0.025;
            innerObject3.IntProp = 651;
            innerObject3.StringProp = "My string property2";

            item2.InnerObject = innerObject3;

            obj.Add(item2);

            ObjectWithInnerObjectAndPrimitivesTest item3 = new ObjectWithInnerObjectAndPrimitivesTest();
            item3.StringProp = "Another string property3";
            item3.IntProp = 23432;

            ObjectWithPrimitivesTest innerObject2 = new ObjectWithPrimitivesTest();
            innerObject2.GuidProp = new Guid("4b72d25f-0a74-47a3-ae3d-c223af92ec8b");
            innerObject2.DatetimeProp = new DateTime(2004, 7, 25, 2, 30, 18);
            innerObject2.DecimalProp = 325000.43M;
            innerObject2.DoubleProp = 0.035;
            innerObject2.IntProp = 652;
            innerObject2.StringProp = "My string property3";

            item3.InnerObject = innerObject2;

            obj.Add(item3);

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<List>
  <ObjectWithInnerObjectAndPrimitivesTest StringProp=""Another string property"" IntProp=""23432"">
    <InnerObject StringProp=""My string property"" GuidProp=""3b72d25f-0a74-47a3-ae3d-c223af92ec8b"" DatetimeProp=""5/25/2002 2:30:18 AM"" DecimalProp=""125000.43"" DoubleProp=""0.005"" IntProp=""65"" />
  </ObjectWithInnerObjectAndPrimitivesTest>
  <ObjectWithInnerObjectAndPrimitivesTest StringProp=""Another string property2"" IntProp=""23432"">
    <InnerObject StringProp=""My string property2"" GuidProp=""4b72d25f-0a74-47a3-ae3d-c223af92ec8b"" DatetimeProp=""6/25/2003 2:30:18 AM"" DecimalProp=""225000.43"" DoubleProp=""0.025"" IntProp=""651"" />
  </ObjectWithInnerObjectAndPrimitivesTest>
  <ObjectWithInnerObjectAndPrimitivesTest StringProp=""Another string property3"" IntProp=""23432"">
    <InnerObject StringProp=""My string property3"" GuidProp=""4b72d25f-0a74-47a3-ae3d-c223af92ec8b"" DatetimeProp=""7/25/2004 2:30:18 AM"" DecimalProp=""325000.43"" DoubleProp=""0.035"" IntProp=""652"" />
  </ObjectWithInnerObjectAndPrimitivesTest>
</List>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializeListOfListsOfStrings()
        {
            List<List<String>> obj = new List<List<String>>();

            List<String> americanCars = new List<String>();
            americanCars.Add("Ford");
            americanCars.Add("Chevrolet");
            americanCars.Add("Dodge");
            obj.Add(americanCars);

            List<String> japaneseCars = new List<String>();
            japaneseCars.Add("Toyota");
            japaneseCars.Add("Honda");
            japaneseCars.Add("Acura");
            obj.Add(japaneseCars);

            List<String> koreanCars = new List<String>();
            koreanCars.Add("Hyundai");
            koreanCars.Add("Kia");
            obj.Add(koreanCars);

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<List>
  <List>
    <String>Ford</String>
    <String>Chevrolet</String>
    <String>Dodge</String>
  </List>
  <List>
    <String>Toyota</String>
    <String>Honda</String>
    <String>Acura</String>
  </List>
  <List>
    <String>Hyundai</String>
    <String>Kia</String>
  </List>
</List>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        /// <summary>
        /// Tests calling a non default constructor during deserialization
        /// </summary>
        [TestMethod()]
        public void SerializeSimpleParentWithChild()
        {
            SimpleParentObject parent = new SimpleParentObject();
            parent.Name = "TheParent";

            SimpleChildObject child1 = new SimpleChildObject(parent);
            child1.Name = "Child1";
            parent.Children.Add(child1);

            SimpleChildObject child2 = new SimpleChildObject(parent);
            child2.Name = "Child2";
            parent.Children.Add(child2);

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(parent);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<SimpleParentObject Name=""TheParent"">
  <Children>
    <SimpleChildObject Name=""Child1"" />
    <SimpleChildObject Name=""Child2"" />
  </Children>
</SimpleParentObject>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializeObjectMissingDictionaryItemAttribute()
        {
            ObjectMissingDictionaryItemAttribute obj = new ObjectMissingDictionaryItemAttribute();

            obj.Dictionary.Add("A", "A");
            obj.Dictionary.Add("B", "B");
            obj.Dictionary.Add("C", "C");

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<ObjectMissingDictionaryItemAttribute>
  <Dictionary>
    <Dictionary>A</Dictionary>
    <Dictionary>B</Dictionary>
    <Dictionary>C</Dictionary>
  </Dictionary>
</ObjectMissingDictionaryItemAttribute>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializeObjectWithStringKeyDictionaryOfStrings()
        {
            ObjectWithStringKeyDictionaryOfStrings obj = new ObjectWithStringKeyDictionaryOfStrings();

            obj.Values.Add("1", "A");
            obj.Values.Add("2", "B");
            obj.Values.Add("3", "C");

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            String expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<ObjectWithStringKeyDictionaryOfStrings>
  <Values>
    <Values>A</Values>
    <Values>B</Values>
    <Values>C</Values>
  </Values>
</ObjectWithStringKeyDictionaryOfStrings>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        #region Extra

        /// <summary>
        ///A test for SerializeToString
        ///</summary>
        [TestMethod()]
        public void SerializeToStringSimpleObjectTest()
        {
            SampleObject obj = new SampleObject();
            obj.Name = "MyName";
            obj.Data = "MyData";

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            string expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<SampleObject Data=""MyData"" Name=""MyName"" />";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        /// <summary>
        ///A test for SerializeToString
        ///</summary>
        [TestMethod()]
        public void SerializeToStringSimpleObjectWithNullValuePropertyTest()
        {
            SampleObject obj = new SampleObject();
            obj.Name = "MyName";

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            string expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<SampleObject Name=""MyName"" />";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        /// <summary>
        ///A test for SerializeToString
        ///</summary>
        [TestMethod()]
        public void SerializeToStringNotTooComplexObjectTest()
        {
            NotTooComplexTestObject obj = new NotTooComplexTestObject();
            obj.Name = "MyName";
            obj.Class = "MyClass";
            obj.Number = 5;
            obj.Text = "My short text";

            obj.SampleObjects = new List<SampleObject>();

            SampleObject sampleObject1 = new SampleObject();
            sampleObject1.Name = "MyName1";
            sampleObject1.Data = "MyData1";

            obj.SampleObjects.Add(sampleObject1);

            SampleObject sampleObject2 = new SampleObject();
            sampleObject2.Name = "MyName2";
            sampleObject2.Data = "MyData2";

            obj.SampleObjects.Add(sampleObject2);

            SampleObject sampleObject3 = new SampleObject();
            sampleObject3.Name = "MyName3";
            sampleObject3.Data = "MyData3";

            obj.SampleObjects.Add(sampleObject3);

            obj.InnerObject = "MyInnerObject";

            InnerObjectWithProperties innerObjectWithProperties = new InnerObjectWithProperties();
            innerObjectWithProperties.Prop1 = "MyProp1";
            innerObjectWithProperties.Prop2 = "MyProp2";

            obj.InnerObjectWithProperties = innerObjectWithProperties;

            obj.Names = new List<String>();
            obj.Names.Add("Name1");
            obj.Names.Add("Name2");
            obj.Names.Add("Name3");
            obj.Names.Add("Name4");

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            string expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<NotTooComplexTestObject Text=""My short text"" Class=""MyClass"" Name=""MyName"" Number=""5"">
  <Inner>MyInnerObject</Inner>
  <InnerObjectWithProperties Prop2=""MyProp2"" Prop1=""MyProp1"" />
  <Names>
    <Name>Name1</Name>
    <Name>Name2</Name>
    <Name>Name3</Name>
    <Name>Name4</Name>
  </Names>
  <SampleObjects>
    <SampleObject Data=""MyData1"" Name=""MyName1"" />
    <SampleObject Data=""MyData2"" Name=""MyName2"" />
    <SampleObject Data=""MyData3"" Name=""MyName3"" />
  </SampleObjects>
</NotTooComplexTestObject>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        /// <summary>
        ///A test for SerializeToString
        ///</summary>
        [TestMethod()]
        public void SerializeToStringObjectWithDictionaryTest()
        {
            PersisterInfo obj = new PersisterInfo();
            obj.Name = "MyPersister";
            obj.ConnectionName = "MyConnectionName";

            obj.ObjectWithArray = new ObjectWithArray();
            obj.ObjectWithArray.SampleObjects = new SampleObject[3];

            SampleObject sampleObject1 = new SampleObject();
            sampleObject1.Name = "SampleName1";
            sampleObject1.Data = "SampleData1";

            obj.ObjectWithArray.SampleObjects[0] = sampleObject1;

            SampleObject sampleObject2 = new SampleObject();
            sampleObject2.Name = "SampleName2";
            sampleObject2.Data = "SampleData2";

            obj.ObjectWithArray.SampleObjects[1] = sampleObject2;

            SampleObject sampleObject3 = new SampleObject();
            sampleObject3.Name = "SampleName3";
            sampleObject3.Data = "SampleData3";

            obj.ObjectWithArray.SampleObjects[2] = sampleObject3;

            obj.Commands = new Dictionary<String, CommandInfo>();

            CommandInfo commandInfo1 = new CommandInfo();
            commandInfo1.Name = "CmdInfo1";
            commandInfo1.Text = "SELECT * FROM CmdInfo1";
            commandInfo1.Type = "Text";

            obj.Commands.Add("CmdInfo1", commandInfo1);

            CommandInfo commandInfo2 = new CommandInfo();
            commandInfo2.Name = "CmdInfo2";
            commandInfo2.Text = "SELECT * FROM CmdInfo2";
            commandInfo2.Type = "StoredProcedure";

            obj.Commands.Add("CmdInfo2", commandInfo2);

            CommandInfo commandInfo3 = new CommandInfo();
            commandInfo3.Name = "CmdInfo3";
            commandInfo3.Text = "SELECT * FROM CmdInfo3";
            commandInfo3.Type = "Table";

            obj.Commands.Add("CmdInfo3", commandInfo3);

            obj.PredefinedCommand = new CommandInfo();
            obj.PredefinedCommand.Name = "PredefinedCommand";
            obj.PredefinedCommand.Text = "SELECT * FROM PredefinedCommand";
            obj.PredefinedCommand.Type = "Text";

            obj.PostdefinedCommand = new CommandInfo();
            obj.PostdefinedCommand.Name = "PostdefinedCommand";
            obj.PostdefinedCommand.Text = "SELECT * FROM PostdefinedCommand";
            obj.PostdefinedCommand.Type = "Text";

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            string expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<PersisterInfo Name=""MyPersister"" ConnectionName=""MyConnectionName"">
  <ObjectWithArray>
    <SampleObjects>
      <SampleObject Data=""SampleData1"" Name=""SampleName1"" />
      <SampleObject Data=""SampleData2"" Name=""SampleName2"" />
      <SampleObject Data=""SampleData3"" Name=""SampleName3"" />
    </SampleObjects>
  </ObjectWithArray>
  <Commands>
    <CommandInfo Name=""CmdInfo1"" Text=""SELECT * FROM CmdInfo1"" Type=""Text"" />
    <CommandInfo Name=""CmdInfo2"" Text=""SELECT * FROM CmdInfo2"" Type=""StoredProcedure"" />
    <CommandInfo Name=""CmdInfo3"" Text=""SELECT * FROM CmdInfo3"" Type=""Table"" />
    <CommandInfo Name=""PredefinedCommand"" Text=""SELECT * FROM PredefinedCommand"" Type=""Text"" />
    <CommandInfo Name=""PostdefinedCommand"" Text=""SELECT * FROM PostdefinedCommand"" Type=""Text"" />
  </Commands>
  <PredefinedCommand Name=""PredefinedCommand"" Text=""SELECT * FROM PredefinedCommand"" Type=""Text"" />
  <PostdefinedCommand Name=""PostdefinedCommand"" Text=""SELECT * FROM PostdefinedCommand"" Type=""Text"" />
</PersisterInfo>";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializeToStringObjectWithIgnoredXmlAttributesTest()
        {
            ObjectWithIgnoredXmlAttributes obj = new ObjectWithIgnoredXmlAttributes();
            obj.Name = "MyName";

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            string expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<ObjectWithIgnoredXmlAttributes />";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        [TestMethod()]
        public void SerializeToStringObjectWithEnumerationPropertyTest()
        {
            ObjectWithEnumerationProperty obj = new ObjectWithEnumerationProperty();
            obj.WeekDay = ObjectWithEnumerationProperty.WeekDays.Saturday;

            XmlObjectSerializer serializer = XmlObjectSerializer.GetSerializer(obj);
            string expected =
@"<?xml version=""1.0"" encoding=""utf-16""?>
<ObjectWithEnumerationProperty WeekDay=""Saturday"" />";

            Assert.AreEqual(expected, serializer.SerializeToString());
        }

        #endregion
    } 
}
